package com.dhp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dhp.Common.ErrorCode;
import com.dhp.Enum.teamStatus;
import com.dhp.Exception.exception;
import com.dhp.domain.Team;
import com.dhp.domain.User;
import com.dhp.domain.UserTeam;
import com.dhp.domain.dto.TeamAddDTO;
import com.dhp.domain.dto.showTeamsDTO;
import com.dhp.domain.request.MyTeamSearchRequest;
import com.dhp.domain.request.TeamJoinRequest;
import com.dhp.domain.request.TeamQuitRequest;
import com.dhp.domain.request.TeamUpdateRequest;
import com.dhp.domain.vo.teamsVO;
import com.dhp.service.TeamService;
import com.dhp.mapper.TeamMapper;
import com.dhp.service.UserService;
import com.dhp.service.UserTeamService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.dhp.Constant.PageDefaultConstant.PAGE_SIZE;
import static com.dhp.Constant.SearchTypeConstant.SEARCH_MY_CRE;
import static com.dhp.Constant.SearchTypeConstant.SEARCH_MY_JOIN;
import static com.dhp.Constant.UserConstant.DEFAULT_USER_ROLE;

/**
* @author Dhp
* @description 针对表【team(队伍信息)】的数据库操作Service实现
* @createDate 2024-02-18 18:18:45
*/
@Service
@Slf4j
public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team>
    implements TeamService{

    @Autowired
    private UserService userService;
    @Autowired
    private TeamMapper teamMapper;
    @Autowired
    private UserTeamService userTeamService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Team addTeam(TeamAddDTO teamAddDTO, HttpServletRequest request) {
        //1. 判空
        if (BeanUtil.isEmpty(teamAddDTO)){
            throw new exception(ErrorCode.PARAMS_EMPTY,"未接收到队伍信息");
        }
        //2. 获取登录用户
        User currentUser = userService.getCurrentUser(request);
        if (currentUser == null){
            throw new exception(ErrorCode.NOT_LOGIN);
        }
        Long userId = currentUser.getId();
        //3. 创建队伍插入信息
        Team team = new Team();
        BeanUtils.copyProperties(teamAddDTO , team);
        team.setTeamName(teamAddDTO.getName());
        team.setUserId(userId);
        this.save(team);
        //4. 缓存用户队伍信息
        UserTeam userTeam = new UserTeam();
        userTeam.setTeamId(team.getId());
        userTeam.setUserId(currentUser.getId());
        userTeam.setJoinTime(new Date());
        userTeamService.save(userTeam);
        return team;
    }

    @Override
    public List<teamsVO> showTeams(showTeamsDTO teamsDTO, HttpServletRequest request) {
        Date now = new Date();
        String searchText = teamsDTO.getSearchText();
        //1. 判空
        if (BeanUtil.isEmpty(teamsDTO)){
            throw new exception(ErrorCode.PARAMS_EMPTY , "请求参数为空");
        }
        User currentUser = userService.getCurrentUser(request);
        if (currentUser == null){
            throw new exception(ErrorCode.NOT_LOGIN);
        }
        //2. 查询队伍信息
        QueryWrapper<Team> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(teamsDTO.getStatus() != null ,"status" , teamsDTO.getStatus());
        //为查询自己创建的队伍提供方便 提高方法复用
        if (SEARCH_MY_CRE.equals(teamsDTO.getSearchType())){
            queryWrapper.eq("user_id" , currentUser.getId());
        }
        //为查询自己加入的队伍提供方便 提高方法复用
        if (SEARCH_MY_JOIN.equals(teamsDTO.getSearchType())){
            if (CollectionUtils.isEmpty(teamsDTO.getIdList())){
                return Collections.emptyList();
            }
            queryWrapper.in("id" , teamsDTO.getIdList());
        }
        if (!StringUtils.isEmpty(teamsDTO.getSearchText())){
            queryWrapper.and(qw -> qw.like("team_name" ,searchText).or().like("description" , searchText));
        }
        Page<Team> teamPage = teamMapper.selectPage(new Page<>(teamsDTO.getPageNum(), teamsDTO.getPageNum(), PAGE_SIZE), queryWrapper);
        if (teamPage == null){
            throw new exception(ErrorCode.SYSTEM_ERROR);
        }
        //3. 构造返回数据
        List<teamsVO> teamsVOList = new ArrayList<>();
        //符合条件的teamid队列
        List<Long> idList = new ArrayList<>();
        for (Team record : teamPage.getRecords()) {
            //如果队伍过期不展示
            if (record.getExpireTime()!= null && record.getExpireTime().before(now)) {
                continue;
            }
            //判断队伍是否为私有
            if (teamStatus.PRIVATE.getValue().equals(record.getStatus())) {
                if (!userService.CheckAuthority(request) && !currentUser.getId().equals(record.getUserId()))
                    continue;
            }
            idList.add(record.getId());
            teamsVO teamsVO = new teamsVO();
            teamsVO.setName(record.getTeamName());
            BeanUtil.copyProperties(record , teamsVO);
            teamsVOList.add(teamsVO);
        }

        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        queryWrapper.in("id" , idList);
        List<UserTeam> list = userTeamService.list(userTeamQueryWrapper);
        Map<Long, List<UserTeam>> userTeamMap = list.stream().collect(Collectors.groupingBy(UserTeam::getTeamId));

        //给返回数据设置加入人数
        teamsVOList.forEach(a -> {
            a.setHasJoinNum((long)userTeamMap.get(a.getId()).size());
        });

        return  teamsVOList;
    }

    @Override
    public teamsVO getTeamInfo(Long teamId) {
        if (teamId == null || teamId <= 0){
            throw new exception(ErrorCode.PARAMS_ERROR);
        }
        Team teamInfo = this.getById(teamId);
        teamsVO teamVO = new teamsVO();
        BeanUtil.copyProperties(teamInfo , teamVO);
        teamVO.setName(teamInfo.getTeamName());
        return teamVO;
    }

    @Override
    public Boolean teamUpdate(TeamUpdateRequest teamUpdateRequest, HttpServletRequest request) {
        //判断参数是否为空
        if (BeanUtil.isEmpty(teamUpdateRequest)){
            throw new exception(ErrorCode.PARAMS_ERROR);
        }
        //判断队伍是否存在
        Team oldTeam = teamMapper.selectById(teamUpdateRequest.getId());
        if (oldTeam == null){
            throw new exception(ErrorCode.NOT_IN_DB,"队伍不存在");
        }
        //判断当前用户是否为队伍的队长
        User currentUser = userService.getCurrentUser(request);
        if (currentUser == null){
            throw new exception(ErrorCode.NOT_LOGIN);
        }
        if (currentUser.getId() != teamUpdateRequest.getUserId() && currentUser.getStatus().equals(DEFAULT_USER_ROLE)){
            throw new exception(ErrorCode.NO_AUTH,"您无权修改");
        }
        //修改队伍信息
        BeanUtil.copyProperties(teamUpdateRequest , oldTeam);
        boolean b = this.updateById(oldTeam);
        //返回修改结果
        return b;
    }

    @Override
    public Boolean joinTeam(TeamJoinRequest teamJoinRequest, HttpServletRequest request) {
        //TODO 加锁防止多次重复加入
        //判段参数是否为空
        if (BeanUtil.isEmpty(teamJoinRequest)){
            throw new exception(ErrorCode.PARAMS_EMPTY);
        }
        //判断队伍是否存在
        Long teamId = teamJoinRequest.getTeamId();
        if (teamId == null || teamId <= 0){
            throw new exception(ErrorCode.PARAMS_ERROR);
        }
        Team target = teamMapper.selectById(teamId);
        if (target == null){
            throw new exception(ErrorCode.NOT_IN_DB , "该队伍不存在或者已经过期");
        }
        //判断是否已经加入该队伍
        User currentUser = userService.getCurrentUser(request);
        LambdaQueryWrapper<UserTeam> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserTeam::getTeamId , teamJoinRequest.getTeamId()).eq(UserTeam::getUserId , currentUser.getId());
        long count = userTeamService.count(queryWrapper);
        if (count != 0){
            throw new exception(ErrorCode.BUSINESS_ERROR , "您已在该队伍中");
        }
        //判断该队伍是否已经满人
        QueryWrapper<UserTeam> wrapper = new QueryWrapper<>();
        wrapper.eq("team_id" , teamJoinRequest.getTeamId());
        long num = userTeamService.count(wrapper);
        if (num >= target.getMaxNum()){
            throw new exception(ErrorCode.BUSINESS_ERROR , "队伍人数已满");
        }
        //如果队伍为加密，判断密码
        if (teamStatus.LOCKED.getValue().equals(target.getStatus())){
            if (!target.getPassword().equals(teamJoinRequest.getPassword()))
                throw new exception(ErrorCode.BUSINESS_ERROR , "密码错误");
        }
        //禁止加入私有队伍
        if (teamStatus.PRIVATE.getValue().equals(target.getStatus())){
            throw new exception(ErrorCode.BUSINESS_ERROR , "队伍为私有");
        }
        //修改用户队伍信息
        UserTeam userTeam = new UserTeam();
        userTeam.setTeamId(teamId);
        userTeam.setUserId(currentUser.getId());
        userTeam.setJoinTime(new Date());
        boolean save = userTeamService.save(userTeam);
        return save;
    }

    @Override
    @Transactional
    public Boolean deleteTeam(Long id, HttpServletRequest request) {
        //判断参数是否合法
        if (id == 0 || id <= 0){
            throw new exception(ErrorCode.PARAMS_ERROR);
        }
        //获取当前用户并判断该用户是不是队长或者管理员
        User currentUser = userService.getCurrentUser(request);
        if (currentUser == null){
            throw new exception(ErrorCode.NOT_LOGIN , "用户未登录");
        }
        Team team = this.getById(id);
        if (currentUser.getId() != team.getUserId() && !userService.CheckAuthority(request)){
            throw new exception(ErrorCode.NO_AUTH , "无权限");
        }
        //删除数据库中的信息
        boolean delete = this.removeById(id);
        LambdaQueryWrapper<UserTeam> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserTeam::getTeamId , id);
        boolean remove = userTeamService.remove(queryWrapper);
        return delete && remove;
    }

    @Override
    public List<teamsVO> searchMyTeam(MyTeamSearchRequest teamSearchRequest, HttpServletRequest request) {
        //判断参数是否为空
        if (BeanUtil.isEmpty(teamSearchRequest)){
            throw new exception(ErrorCode.PARAMS_EMPTY);
        }
        //数据库中取出信息
        showTeamsDTO teamsDTO = new showTeamsDTO();
        BeanUtil.copyProperties(teamSearchRequest , teamsDTO);
        teamsDTO.setSearchType(SEARCH_MY_CRE);
        return this.showTeams(teamsDTO, request);
    }

    @Override
    public List<teamsVO> searchMyjoinTeam(showTeamsDTO showTeamsDTO, HttpServletRequest request) {
        //判断参数是否为空
        if (BeanUtil.isEmpty(showTeamsDTO)){
            throw new exception(ErrorCode.PARAMS_EMPTY);
        }
        //获取当前用户
        User currentUser = userService.getCurrentUser(request);
        if (currentUser == null){
            throw new exception(ErrorCode.NOT_LOGIN , "用户未登录");
        }
        Long userId = currentUser.getId();
        //从数据库中取出信息
        //查出加入的队伍id
        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id" , userId);
        List<UserTeam> list = userTeamService.list(queryWrapper);
        List<Long> idList = list.stream().map(UserTeam::getTeamId).collect(Collectors.toList());
        //查询队伍详细信息
        showTeamsDTO.setIdList(idList);
        showTeamsDTO.setSearchType(SEARCH_MY_JOIN);
        List<teamsVO> teamsVOList = this.showTeams(showTeamsDTO, request);
        return teamsVOList;
    }

    @Override
    public boolean quitTeam(TeamQuitRequest teamQuitRequest , HttpServletRequest request) {
        //判空
        if (BeanUtil.isEmpty(teamQuitRequest)){
            throw new exception(ErrorCode.PARAMS_EMPTY);
        }
        //判断当前用户是否已经加入该队伍
        User currentUser = userService.getCurrentUser(request);
        if (currentUser == null){
            throw new exception(ErrorCode.NOT_LOGIN , "请先登录");
        }
        Long userId = currentUser.getId();
        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id" , userId).eq("team_id" , teamQuitRequest.getTeamId());
        long count = userTeamService.count(queryWrapper);
        if (count == 0){
            throw new exception(ErrorCode.BUSINESS_ERROR , "您未加入该队伍");
        }
        //删除用户队伍表中的相关信息
        boolean remove = userTeamService.remove(queryWrapper);
        return remove;
    }

    public Date TimeFormat(Date date){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
        simpleDateFormat.applyPattern("yyyy年MM月dd日");
        String formatDate = simpleDateFormat.format(date);
        try {
            Date parse = simpleDateFormat.parse(formatDate);
            return parse;

        } catch (ParseException e) {
            throw new RuntimeException(e);
        }

    }

}




